home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 4 / Precision Software Applications Silver Collection Volume 4 (1993).iso / stats / chadyn.exe / YXWINDOW.C < prev   
C/C++ Source or Header  |  1988-12-08  |  15KB  |  451 lines

  1. /* YWINDOWS - routines for dealing with X Windows. */
  2.  
  3. #include "yinclud.h"
  4. #ifdef X11
  5. #include <X11/Xutil.h>
  6. #include <setjmp.h>
  7. #define BESTWIDTH 640
  8. #define BESTHEIGHT 480
  9. #define MINPIXELS 400
  10. #define BACKSPACE '\010'
  11. #define RUBOUT '\177'
  12. #define LINEKILL '\025'
  13. #define RETURN '\015'
  14. #define EOT '\004'
  15. #define MAXPTS 50
  16. #define iserase(x) ((x) == BACKSPACE || (x) == RUBOUT)
  17. #define isprintable(x) ((x) == '\n' || (x) >= '\040' && (x) <= '\176')
  18. #define bscrt() {putchar(BACKSPACE); putchar(' '); putchar(BACKSPACE);}
  19.  
  20. static char     kbbuf[MAXCHAR + 1];/* keystroke buffer */
  21. static int      bufcount = 0;    /* number of chars in kbbuf  */
  22.  
  23. #define progname *argvGlob
  24. #define streq(x, y) (strcmp(x, y) == 0)
  25. #define QUIT exit(1)
  26. #define die(x) {fprintf(stderr, "%s: %s(file %s, line %d)\n", progname, x,\
  27. __FILE__, __LINE__); QUIT; }
  28.  
  29. XSizeHints sizehint = {
  30.     PAllHints,        /* flags */
  31.         100, 100,    /* user specified x, y */
  32.         BESTWIDTH, BESTHEIGHT,/* user specified width, height */
  33.         BESTWIDTH, BESTHEIGHT,/* program spec. min width, height */
  34.         BESTHEIGHT * 2, BESTHEIGHT * 2,
  35.                 /* program spec. max width, height */
  36.         100, 100,    /* program spec. width, height inc */
  37.         { 1, 2 },    /* min aspect */
  38.         { 3, 1 }    /* max aspect */
  39. };
  40.  
  41. jmp_buf    key_env;    /* used by AWAITKEY to save stack state as we wait
  42.              * for a key to be pressed */
  43.  
  44. /* -------------------------------------------------------------------- */
  45. /* SETVIDMODE - initialize X windows */
  46. SetVidMode() {
  47.     XWindowAttributes swa, gswa;
  48.     char   *option;
  49.     int     val;
  50.     if((x_dpy = XOpenDisplay(NULL)) == NULL)
  51.         die("can't get display");
  52.  
  53.     x_screennbr = DefaultScreen(x_dpy);
  54.  
  55.     /* Get user's favorite values for foreground, background, and
  56.      * width of window border.  First initialize a default background.
  57.      */
  58.     x_backcolor = BlackPixel(x_dpy, x_screennbr);
  59.     x_forecolor = WhitePixel(x_dpy, x_screennbr);
  60.  
  61.     if((option = XGetDefault(x_dpy, progname, "BorderWidth")) != NULL &&
  62.             (val = atoi(option)) > 1)
  63.         x_borderwidth = val;
  64.  
  65.     if((option = XGetDefault(x_dpy, progname, "Background")) != NULL) {
  66.         if(streq(option, "black"))
  67.             x_backcolor = BlackPixel(x_dpy, x_screennbr);
  68.         else
  69.             x_backcolor = WhitePixel(x_dpy, x_screennbr);
  70.     }
  71.     if((option = XGetDefault(x_dpy, progname, "Foreground")) != NULL) {
  72.         if(streq(option, "black"))
  73.             x_forecolor = BlackPixel(x_dpy, x_screennbr);
  74.         else
  75.             x_forecolor = WhitePixel(x_dpy, x_screennbr);
  76.     }
  77.     if(x_backcolor == x_forecolor) {
  78.         fprintf(stderr, "%s: identical background & foreground\n:",
  79.                 progname);
  80.         x_backcolor = WhitePixel(x_dpy, x_screennbr);
  81.         x_forecolor = BlackPixel(x_dpy, x_screennbr);
  82.     }
  83.     /* Create a window */
  84.  
  85.     if((x_window = XCreateSimpleWindow(x_dpy, DefaultRootWindow(x_dpy),
  86.                     sizehint.x, sizehint.y, sizehint.width, sizehint.height,
  87.                     x_borderwidth, x_forecolor, x_backcolor)) == 0)
  88.         die("XCreateSimpleWindow failed");
  89.  
  90.     XSetStandardProperties(x_dpy, x_window, "Dynamics", "Dynamics",
  91.             None, argvGlob, argcGlob, &sizehint);
  92.  
  93.     /* Use the default color map and set gravity(I still don't understand
  94.      * this yet)
  95.      */
  96.     /* swa.colormap = DefaultColormap(x_dpy, x_screennbr); */
  97.     swa.bit_gravity = CenterGravity;
  98.     XChangeWindowAttributes(x_dpy, x_window, CWBitGravity,
  99.             &swa);
  100.  
  101.     /* Create a Graphics Context for this window, using the selected
  102.      * values of foreground and background color
  103.      */
  104.  
  105.     x_gcval.foreground = x_forecolor;
  106.     x_gcval.background = x_backcolor;
  107.     x_gc = XCreateGC(x_dpy, x_window, GCForeground | GCBackground,
  108.             &x_gcval);
  109.  
  110.     /* Do likewise for blanking out stuff */
  111.  
  112.     x_gcval.foreground = x_backcolor;
  113.     x_gcval.background = x_forecolor;
  114.     x_gcblank = XCreateGC(x_dpy, x_window, GCForeground | GCBackground,
  115.             &x_gcval);
  116.  
  117.     /* We are interested in Exposure events, KeyPressed events,
  118.      * and mouse motions
  119.      */
  120.     XSelectInput(x_dpy, x_window, x_eventmask);
  121.  
  122.     /* Now map the window to the screen */
  123.  
  124.     XMapWindow(x_dpy, x_window);
  125.  
  126.     /* Query the window size */
  127.  
  128.     (void) XGetWindowAttributes(x_dpy, x_window, &gswa);
  129.     scrncols = gswa.width;
  130.     scrnrows = gswa.height;
  131.     return;
  132. }
  133. /* -------------------------------------------------------------------- */
  134. /* SETPIXEL - turn on the pixel at P. 
  135.  * Normally we save up the points to be plotted in a buffer and plot
  136.  * them all at once with one call to XDrawPoints in order to save the
  137.  * overhead of many calls to the X server.  However, when we are in
  138.  * single step mode (cycle > 0), then we plot one dot at a time.
  139.  */
  140. setPixel(p)
  141. POINT    *p;
  142. {
  143. #ifdef NEW
  144.     XDrawPoint(x_dpy, x_window, x_gc, p->x, p->y);
  145. #else
  146.     static XPoint    ptbuf[MAXPTS];
  147.     static int    ptcount = 0;
  148.  
  149.     if(cycle > 0)  {
  150.         if(ptcount > 0)  {    /* dump buffered pts to screen */
  151.             ptbuf[ptcount].x = p->x;
  152.             ptbuf[ptcount].y = p->y;
  153.             ptcount++;
  154.             XDrawPoints(x_dpy, x_window, x_gc, ptbuf, ptcount,
  155.                 CoordModeOrigin);
  156.             ptcount = 0;
  157.         } else
  158.             XDrawPoint(x_dpy, x_window, x_gc, p->x, p->y);
  159.     } else {
  160.         ptbuf[ptcount].x = p->x;    /* buffer & plot when full */
  161.         ptbuf[ptcount].y = p->y;
  162.         ptcount++;
  163.         if(ptcount == MAXPTS)  {
  164.             XDrawPoints(x_dpy, x_window, x_gc, ptbuf, ptcount,
  165.                 CoordModeOrigin);
  166.             ptcount = 0;
  167.         }
  168.     }
  169.     return;
  170. #endif    /* NEW */
  171. }
  172. /* -------------------------------------------------------------------- */
  173. /* SCR_CLR - clear the window. */
  174. scr_clr()
  175. {
  176.     /* We need to remember whether the crosses are on, so that we
  177.      * can clear the background in the pixmaps behind them
  178.      * before we redraw them on the screen.
  179.      */
  180.     int    need0 = IsCross0Set;
  181.     int    need1 = IsCross1Set;
  182.  
  183.     if(need0)
  184.         turnoff(BIGCROSS);
  185.     if(need1)
  186.         turnoff(SMALLCROSS);
  187.     XClearWindow(x_dpy, x_window);
  188.     if(need0)  {
  189.         cross(crossX0, crossY0, SCRNCROSSWIDTH, SCRNCROSSHEIGHT, SCRN, 
  190.             BIGCROSS);
  191.         IsCross0Set = 1;
  192.     }
  193.     if(need1)  {
  194.         cross(crossX1, crossY1, SCRNCROSSWIDTH / 2,
  195.             SCRNCROSSHEIGHT / 2, SCRN, SMALLCROSS);
  196.         IsCross1Set = 1;
  197.     }
  198.     return;
  199. }
  200. /* -------------------------------------------------------------------- */
  201. /* Basic routines for handling the keyboard using X windows. */
  202. /* -------------------------------------------------------------------- */
  203. /* MAPKEY - examine both the KeySym code for the pressed key and the character
  204.  * translation to determine whether we have an alphabetic keystroke or some
  205.  * other key, like an arrow key.
  206.  * XLOOKUPSTRING maps arrow keys to ascii characters so we need to distinguish
  207.  * between them.
  208.  */
  209. int    mapkey(symbol, ch)
  210. register KeySym    symbol;
  211. register int    ch;
  212. {
  213.     if(symbol == XK_Delete || symbol == XK_BackSpace ||
  214.        ch == BACKSPACE)  {            /* map to backspace */
  215.         symbol = (KeySym) BACKSPACE;
  216.     } else if(symbol == XK_Return || symbol == XK_Linefeed ||
  217.        ch == RETURN || ch == LINEFEED)  { /* map to control-M */
  218.         symbol = (KeySym) RETURN;
  219.     } else if(ch == LINEKILL)  {      /* map to line kill char */
  220.         symbol = (KeySym) LINEKILL;
  221.     } else if(ch == EOT)  {    /* control-D for EOF */
  222.         symbol = (KeySym) 0;
  223.     } else if(symbol == XK_Escape) {
  224.         symbol = (KeySym) ch;    /* ASCII escape */
  225.     } else
  226.         symbol = (KeySym) ch;
  227.     return((int) symbol);
  228. }
  229. /* -------------------------------------------------------------------- */
  230. /* KEYCHECK - return 0 if no key has been hit.  Otherwise return the KeySym of
  231.  * the most recently struck character.  The typed character is NOT stored in
  232.  * the keyboard buffer!
  233.  */
  234. int     keycheck() 
  235. {
  236.         XEvent event;
  237.     KeySym    symbol = (KeySym) 0;
  238.     char    ch;
  239.  
  240.     if(XCheckTypedWindowEvent(x_dpy, x_window, KeyPress, &event))
  241.         (void) XLookupString(&event, &ch, 1, &symbol, NULL);
  242.     return(mapkey(symbol, (int) ch));
  243. }
  244. /* -------------------------------------------------------------------- */
  245. /* ALARMHANDLE - spring back to the start of AWAITKEY when the latter
  246.  * times out.
  247.  */
  248. int    alarmhandle()
  249. {
  250.     (void) signal(SIGALRM, SIG_DFL);
  251.     longjmp(key_env, 1);
  252.     return(1);        /* never happens */
  253. }
  254. /* -------------------------------------------------------------------- */
  255. /* AWAITKEY - like KEYCHECK except we block until a key is struck.
  256.  * The typed character is NOT stored in the keyboard buffer.
  257.  * We return NUL if no key is struck within TIMEOUT seconds.
  258.  * A TIMEOUT value of 0 means to wait forever.
  259.  */
  260. int    awaitkey(timeout)
  261. unsigned    timeout;        /* in seconds */
  262. {
  263.         XEvent event;
  264.     KeySym    symbol;
  265.     char    ch;
  266.  
  267.     if(timeout != 0)  {
  268.         (void) signal(SIGALRM, alarmhandle);
  269.         (void) alarm(timeout);
  270.     }
  271.     if(setjmp(key_env) == 0)  {    /* wait for a key */
  272.         XWindowEvent(x_dpy, x_window, KeyPressMask, &event);
  273.         (void) XLookupString(&event, &ch, 1, &symbol, NULL);
  274.     } else             /* timed out */
  275.         symbol = (KeySym) 0;
  276.     (void) alarm(0);    /* cancel the alarm */
  277.     return(mapkey(symbol, (int) ch));
  278. }
  279. /* -------------------------------------------------------------------- */
  280. /* CHKKEYSTATUS - return 1 if a key has been hit and 0 otherwise.  
  281.  * We keep the keypressed event in the queue however so that keycheck()
  282.  * can later determine which key has been pressed.
  283.  */
  284. int     ChkKeyStatus() 
  285. {
  286.         XEvent event;
  287.     Bool    yes;
  288.  
  289.     if(yes = XCheckWindowEvent(x_dpy, x_window, KeyPressMask, &event))
  290.         XPutBackEvent(x_dpy, &event);
  291.     return((int) yes);
  292. }
  293. /* -------------------------------------------------------------------- */
  294. /* STOREKEY - Get the next character typed from the graphics window and
  295.  * place into the keyboard buffer, manually performing erase and line kill
  296.  * processing.  Return the character typed.
  297.  * Notes:  
  298.  * 1.  We call XWindowEvent to block until a character is read.
  299.  * 2.  We let backspace(control-H) and rubout(DELETE) erase characters,
  300.  *    and control-U(NAK) erase the line, regardless of the current
  301.  *    terminal settings.
  302.  * 3.  It is important that a NUL be placed in KBBUF at the logical
  303.  *    end of the buffer.  That is, we have two ways to track the exent of its
  304.  *    contents:  the value of BUFCOUNT and the location of the NUL.
  305.  * 4.  If the contents of the keyboard buffer would overflow, the excess
  306.  *    characters are silently discarded.
  307.  * 5.  Carriage returns are not mapped to newlines in X windows; they are read
  308.  *    as control-M's from the keyboard and converted to newlines here.
  309.  * 6.  No word erase or line-redraw processing is available in this version.
  310.  * 7.  Control-D is mapped to NUL to simulate an EOF.
  311.  * 8.  Keys which are not standard ASCII characters (e.g. arrow keys)
  312.  *    have the proper keysym code returned, but this is mapped in turn
  313.  *    to an ASCII character.  (For example, the up arrow key is mapped
  314.  *    to a capital R, I think, in the buffer, but the function returns
  315.  *    an integer code between 128 and 255 so that the value of the function,
  316.  *    interpreted as a KeySym, correctly indicates that an arrow key has
  317.  *    been pressed.)
  318.  */
  319. int     storekey() 
  320. {
  321.     XEvent event;
  322.     char    ch;
  323.     KeySym    symbol = (KeySym) 0;
  324.  
  325.     /* Get all pending KeyPress events and place in the buffer.
  326.      * If the buffer overflows, silently discard the excess characters.
  327.      * We have to do extra checking of CH and SYMBOL because the latter
  328.      * mapping doesn't handle control-key combinations.
  329.      */
  330.  
  331.     XWindowEvent(x_dpy, x_window, KeyPressMask, &event);
  332.     if(bufcount < MAXCHAR &&
  333.             XLookupString(&event, &ch, 1, &symbol, NULL) > 0) {
  334.         symbol = (KeySym) mapkey(symbol, (int) ch);
  335.         switch(symbol)  {
  336.         case BACKSPACE: /* erase only on current line */
  337.             if(bufcount > 0 && kbbuf[bufcount-1] != RETURN)
  338.                 kbbuf[--bufcount] = '\0';
  339.             break;
  340.         case RETURN:
  341.             kbbuf[bufcount++] = RETURN;
  342.             break;
  343.         case LINEKILL: {      /* erase current line only */
  344.                 register char  *b = kbbuf + bufcount - 1;
  345.                 while(bufcount > 0 && *b != RETURN) {
  346.                     *b-- = '\0';
  347.                     bufcount--;
  348.                 }
  349.             }
  350.             break;
  351.         case '\0':        /* end of file */
  352.             kbbuf[bufcount] = '\0';
  353.             break;
  354.         default:
  355.             kbbuf[bufcount++] = ch;
  356.             break;
  357.         }
  358.     }
  359.     return((int) symbol);
  360. }
  361. /* -------------------------------------------------------------------- */
  362. /* GETKBS - get a string from the keyboard buffer, if available.
  363.  * A string is considered available if a newline character is in the buffer.
  364.  * All characters are copied from the buffer into STRING up to the newline;
  365.  * the newline is replaced with a NUL in STRING, and the contents of
  366.  * KBBUF are bumped down to the front.  
  367.  * Return value is the number of characters copied.  If no newline exists,
  368.  * then STRING is unchanged and the function returns 0.  No check is made
  369.  * for overflow in STRING.
  370.  */
  371. int     getkbs(string)
  372. char   *string;
  373. {
  374.     register char  *b;
  375.     register char  *s = string;
  376.     register int    k;
  377.  
  378.     for(b = kbbuf; *b != RETURN && *b != '\0'; b++);  /* find newline */
  379.     if(*b == RETURN) {
  380.         for(b = kbbuf; *b != RETURN; b++)
  381.             *s++ = *b;
  382.         *s++ = '\0';    /* return at least 1 */
  383.         k = (int) (b - kbbuf) + 1;      /* +1 to skip newline */
  384.         for(b = kbbuf; k < bufcount; k++) /* bump down buffer */
  385.             *b++ = kbbuf[k];
  386.         *b = '\0';              /* this is very important! */
  387.         bufcount = (int) (b - kbbuf);
  388.     }
  389.     return((int) (s - string));
  390. }
  391. /* -------------------------------------------------------------------- */
  392. /* CRTECHO - echo the typed character to the screen.
  393.  * N is the number of characters typed so far.  If the character is LINEKILL
  394.  * (NAK), then erase to the beginning of the line.  All printable characters
  395.  * are echoed.  Control characters that are not printing characters are
  396.  * echoed as percent signs.
  397.  * Note:  We echo backspace-space-backspace to erase characters.
  398.  */
  399. void crtecho(ch, n)
  400. register int   ch;
  401. register int    n;
  402. {
  403.     register int    j;
  404.  
  405.     if(iserase(ch) && n > 0) {
  406.         bscrt();
  407.     } else if(ch == LINEKILL) {
  408.         for(j = 0; j < n; j++) {
  409.             bscrt();
  410.         }
  411.     } else if(isprintable(ch)) {
  412.         putchar(ch);
  413.     }
  414.     else
  415.         putchar('%');
  416.     fflush(stdout);
  417.     return;
  418. }
  419. /* -------------------------------------------------------------------- */
  420. /* XWFGETS - get a string from the keyboard buffer.  Manually perform all
  421.  * input editing and echoing to the standard output(assumed to be the
  422.  * screen.)  The routine copies characters until a newline is scanned,
  423.  * blocking for the reads if needed.
  424.  * The keyboard buffer contents are copied down as needed.
  425.  * The function returns a pointer to a static string which is overwritten
  426.  * on each call.
  427.  */
  428. char   *xwfgets() {
  429.     static char     string[MAXCHAR + 1];
  430.     register int    n;
  431.     register int    ch;
  432.  
  433.     if(getkbs(string) > 0)
  434.         printf("%s\n", string);
  435.     else {
  436.         for(n = 0; (ch = storekey()) != RETURN; n++)
  437.             if(ch != '\0')
  438.                 crtecho(ch, n);
  439.         crtecho('\n', n);    /* place final newline */
  440.         (void) getkbs(string);
  441.     }
  442.     return(&string[0]);
  443. }
  444. /* -------------------------------------------------------------------- */
  445. setRGBColor()
  446. {
  447.     PRINT "Color is not implemented under X windows\n");
  448.     return;
  449. }
  450. #endif                /* X11 */
  451.